package com.coocaa.app.lib.cleaner.mgr;

import android.content.Context;
import android.support.test.rule.ActivityTestRule;
import android.util.Log;

import com.coocaa.app.lib.cleaner.TestActivity;
import com.coocaa.app.lib.cleaner.deleter.apk.ApkDeleterFactory;
import com.coocaa.app.lib.cleaner.deleter.other.OtherDataDeleterFactory;
import com.coocaa.app.lib.cleaner.deleter.pkgcache.PackageCacheDeleterFactory;
import com.coocaa.app.lib.cleaner.deleter.pkgdata.PackageDataDeleterFactory;
import com.coocaa.app.lib.cleaner.mgr.impl.DataHolderImpl;

import junit.framework.Assert;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mockito;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * Created by lu on 17-4-12.
 */

public class CleanerTest {
    @Rule
    public ActivityTestRule<TestActivity> testActivityRule = new ActivityTestRule<TestActivity>(
            TestActivity.class);

    @Before
    public void setUp() throws Exception {


    }

    @Test
    public void name() throws Exception {
        final CountDownLatch latch = new CountDownLatch(1);
        Context context = testActivityRule.getActivity();
        Cleaner cleaner = CleanerManager.manager.create(context);
        cleaner.setCleanerListener(new Cleaner.CleanerListener() {
            @Override
            public void onScanStart() {
                Log.d("CT", "onScanStart");
            }

            @Override
            public void onScanEnd() {
                Log.d("CT", "onScanEnd");
                latch.countDown();
            }

            @Override
            public void onApkRubbishUpdate(DataHolder.ApkRubbish apkRubbish, String apkFile) {
                Log.d("CT", "onApkRubbishUpdate total:" + apkRubbish.size + " file:" + apkFile);
            }

            @Override
            public void onPackageCacheUpdate(DataHolder.PackageCache packageCache, String packageName) {
                Log.d("CT", "onPackageCacheUpdate total:" + packageCache.size + " packageName:" + packageName);
            }

            @Override
            public void onPackageDataUpdate(DataHolder.PackageData packageData, String packageName) {
                Log.d("CT", "onPackageDataUpdate total:" + packageData.size + " packageName:" + packageName);
            }

            @Override
            public void onOtherDataUpdate(DataHolder.OtherData otherData, String file) {
                Log.d("CT", "onOtherDataUpdate total:" + otherData.size + " file:" + file);
            }
        });

        cleaner.startScan();
        latch.await();
    }

    @Test
    public void apkDeleterTest() throws Exception {
        Context context = testActivityRule.getActivity();
        Cleaner cleaner = CleanerManager.manager.create(context);
        DataHolder holder = DataHolderImpl.instance;
        DataHolder.DataHolderListener listener = Mockito.mock(DataHolder.DataHolderListener.class);
        holder.reset(listener);

        List<String> apks = new ArrayList<String>();
        for (int i = 0; i < 10; i++)
            apks.add("apkFile:" + i);
        for (String apk : apks)
            holder.appendAPK(apk);

        DataHolder.ApkRubbish r = cleaner.getApkRubbish();
        Assert.assertNotNull(r);

        ApkDeleterFactory.ApkDeleter.ApkDeleterListener _listener = Mockito.mock(ApkDeleterFactory.ApkDeleter.ApkDeleterListener.class);
        int i = (int) (Math.random() * 10);
        String _apk = apks.get(i);
        apks.remove(i);
        r.delete(context, _apk, _listener);

        Thread.sleep(2 * 1000);
        Mockito.verify(_listener, Mockito.times(1)).onApkDeleterStart(Mockito.anyBoolean(), Mockito.<String>anyList());
        Mockito.verify(_listener, Mockito.times(1)).onApkDeleterEnd(Mockito.anyBoolean(), Mockito.<String>anyList(), Mockito.anyBoolean(), Mockito.anyLong());


        _listener = Mockito.mock(ApkDeleterFactory.ApkDeleter.ApkDeleterListener.class);
        r.delete(context, apks, _listener);
        Thread.sleep(2 * 10 * 1000);
        Mockito.verify(_listener, Mockito.times(1)).onApkDeleterStart(Mockito.anyBoolean(), Mockito.<String>anyList());
        Mockito.verify(_listener, Mockito.times(1)).onApkDeleterEnd(Mockito.anyBoolean(), Mockito.<String>anyList(), Mockito.anyBoolean(), Mockito.anyLong());

        for (String apk : apks) {
            Mockito.verify(_listener, Mockito.times(1)).onApkDeleterStart(Mockito.anyBoolean(), Mockito.<String>anyList());
            Mockito.verify(_listener, Mockito.times(1)).onApkDeleterEnd(Mockito.anyBoolean(), Mockito.<String>anyList(), Mockito.anyBoolean(), Mockito.anyLong());
        }
    }

    @Test
    public void packageCacheDeleterTest() throws Exception {
        Context context = testActivityRule.getActivity();
        Cleaner cleaner = CleanerManager.manager.create(context);
        DataHolder holder = DataHolderImpl.instance;
        DataHolder.DataHolderListener listener = Mockito.mock(DataHolder.DataHolderListener.class);
        holder.reset(listener);

        class A {
            public String packageName;
            public long size;

            public A(String packageName, long size) {
                this.packageName = packageName;
                this.size = size;
            }
        }
        List<A> aa = new ArrayList<A>();
        for (int i = 0; i < 10; i++)
            aa.add(new A("p" + i, (long) (Math.random() * 1000) + 100));
        for (A a : aa)
            holder.appendPackageCache(a.packageName, a.size);

        DataHolder.PackageCache r = cleaner.getPackageCache();
        Assert.assertNotNull(r);

        PackageCacheDeleterFactory.PackageCacheDeleter.PackageCacheDeleterListener _listener =
                Mockito.mock(PackageCacheDeleterFactory.PackageCacheDeleter.PackageCacheDeleterListener.class);
        int i = (int) (Math.random() * 10);
//        A _a = aa.get(i);
        r.delete(context, r.caches.get(i), _listener);
        aa.remove(i);
        Thread.sleep(2 * 1000);
        Mockito.verify(_listener, Mockito.times(1)).onPackageCacheDeleterStart(Mockito.anyBoolean(), Mockito.<String>anyList());
        Mockito.verify(_listener, Mockito.times(1)).onPackageCacheDeleterEnd(Mockito.anyBoolean(), Mockito.<String>anyList(), Mockito.anyBoolean(), Mockito.anyLong());

        _listener =
                Mockito.mock(PackageCacheDeleterFactory.PackageCacheDeleter.PackageCacheDeleterListener.class);
//        List<String> packageNames = new ArrayList<String>();
//        for (A a : aa)
//            packageNames.add(a.packageName);
        r.delete(context, r.caches, _listener);
        Thread.sleep(2 * 10 * 1000);
        Mockito.verify(_listener, Mockito.times(1)).onPackageCacheDeleterStart(Mockito.anyBoolean(), Mockito.<String>anyList());
        Mockito.verify(_listener, Mockito.times(1)).onPackageCacheDeleterEnd(Mockito.anyBoolean(), Mockito.<String>anyList(), Mockito.anyBoolean(), Mockito.anyLong());
        for (DataHolder.SinglePackageCache spc : r.caches) {
            Mockito.verify(_listener, Mockito.times(1)).onPackageCacheDeleterStart(Mockito.anyBoolean(), Mockito.<String>anyList());
            Mockito.verify(_listener, Mockito.times(1)).onPackageCacheDeleterEnd(Mockito.anyBoolean(), Mockito.<String>anyList(), Mockito.anyBoolean(), Mockito.anyLong());
        }
    }


    @Test
    public void packageDataDeleterTest() throws Exception {
        Context context = testActivityRule.getActivity();
        Cleaner cleaner = CleanerManager.manager.create(context);
        DataHolder holder = DataHolderImpl.instance;
        DataHolder.DataHolderListener listener = Mockito.mock(DataHolder.DataHolderListener.class);
        holder.reset(listener);

        class A {
            public String packageName;
            public long size;

            public A(String packageName) {
                this.packageName = packageName;
                this.size = (long) (Math.random() * 1000 + 100);
            }
        }
        List<A> aa = new ArrayList<A>();
        for (int i = 0; i < 10; i++) {
            aa.add(new A("p" + i));
        }
        for (A a : aa)
            holder.appendPackageData(a.packageName, a.size);

        DataHolder.PackageData r = cleaner.getPackageData();
        Assert.assertNotNull(r);

        PackageDataDeleterFactory.PackageDataDeleter.PackageDataDeleterListener _listener =
                Mockito.mock(PackageDataDeleterFactory.PackageDataDeleter.PackageDataDeleterListener.class);
        int i = (int) (Math.random() * r.datas.size());
//        A _a = aa.get(i);
        r.delete(context, r.datas.get(i), _listener);
        aa.remove(i);
        Thread.sleep(2 * 1000);
        Mockito.verify(_listener, Mockito.times(1)).onPackageDataDeleterStart(Mockito.anyBoolean(), Mockito.<String>anyList());
        Mockito.verify(_listener, Mockito.times(1)).onPackageDataDeleterEnd(Mockito.anyBoolean(), Mockito.<String>anyList(), Mockito.anyBoolean(), Mockito.anyLong());

        _listener =
                Mockito.mock(PackageDataDeleterFactory.PackageDataDeleter.PackageDataDeleterListener.class);
//        List<String> packageNames = new ArrayList<String>();
//        for (A a : aa)
//            packageNames.add(a.packageName);
        r.delete(context, r.datas, _listener);
        Thread.sleep(2 * 10 * 1000);
        Mockito.verify(_listener, Mockito.times(1)).onPackageDataDeleterStart(Mockito.anyBoolean(), Mockito.<String>anyList());
        Mockito.verify(_listener, Mockito.times(1)).onPackageDataDeleterEnd(Mockito.anyBoolean(), Mockito.<String>anyList(), Mockito.anyBoolean(), Mockito.anyLong());
        for (DataHolder.SinglePackageData spd : r.datas) {
            Mockito.verify(_listener, Mockito.times(1)).onPackageDataDeleterStart(Mockito.anyBoolean(), Mockito.<String>anyList());
            Mockito.verify(_listener, Mockito.times(1)).onPackageDataDeleterEnd(Mockito.anyBoolean(), Mockito.<String>anyList(), Mockito.anyBoolean(), Mockito.anyLong());
        }
    }

    @Test
    public void otherDeleterTest() throws Exception {
        Context context = testActivityRule.getActivity();
        Cleaner cleaner = CleanerManager.manager.create(context);
        DataHolder holder = DataHolderImpl.instance;
        DataHolder.DataHolderListener listener = Mockito.mock(DataHolder.DataHolderListener.class);
        holder.reset(listener);

        List<String> aa = new ArrayList<String>();
        for (int i = 0; i < 10; i++)
            aa.add("file:" + i);

        for (String a : aa)
            holder.appendOtherData(a);

        DataHolder.OtherData r = cleaner.getOtherData();
        Assert.assertNotNull(r);

        OtherDataDeleterFactory.OtherDataDeleter.OtherDataDeleterListener _listener =
                Mockito.mock(OtherDataDeleterFactory.OtherDataDeleter.OtherDataDeleterListener.class);
        r.delete(context, aa, _listener);

        Thread.sleep(10 * 1000);

        Mockito.verify(_listener, Mockito.times(1)).onOtherDeleteStart();
        Mockito.verify(_listener, Mockito.times(1)).onOtherDataDeleteEnd(Mockito.anyBoolean(), Mockito.anyLong());
    }
}
